home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Object.C < prev    next >
C/C++ Source or Header  |  1992-07-23  |  16KB  |  721 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Object.h"
  6.  
  7. #include "Class.h"
  8. #include "OrdColl.h"
  9. #include "IdDictionary.h"
  10. #include "ObjInt.h"
  11. #include "Error.h"
  12. #include "String.h"
  13. #include "Storage.h"
  14. #include "ProgEnv.h"
  15. #include "System.h"
  16. #include "ObjectTable.h"
  17. #include "AccessMem.h"
  18. #include "MemBuf.h"
  19. #include "CmdNo.h"
  20.   
  21. //---- observing ---------------------------------------------------------
  22.  
  23. static IdDictionary *Observer; 
  24. // dictionary associating a list of observers with an Object
  25.  
  26. static IdDictionary *DelayedChanges; 
  27. // dictionary to store the delayed Change messages, the key is the object pointer
  28. // (IdDictionary) the value is an OrderedCollection of ChangeMessages (see below).
  29. // The first entry of the OrderedCollection is a reference count of the number of
  30. // DelayChanges requests. FlushChanges will be executed when the count drops to 0.
  31. // Whether change messages are delayed is set with the cObjDelayChanges flag
  32.  
  33. ONEXIT(Object)
  34. {
  35.     if (Observer) {
  36.     Observer->FreeValues();
  37.     SafeDelete(Observer);
  38.     }
  39.     if (DelayedChanges) {
  40.     DelayedChanges->FreeAllValues();
  41.     SafeDelete(DelayedChanges);
  42.     }
  43. }
  44.  
  45. class ChangeMessage: public Object {
  46. public:
  47.     void *what;
  48.     int part, id;
  49. public:
  50.     MetaDef(ChangeMessage);
  51.     ChangeMessage(void *w, int p, int i)
  52.     { what= w; part= p; id= i; }
  53. };
  54.  
  55. NewMetaImpl(ChangeMessage,Object, (TX(what), T(part), T(id)));
  56.  
  57. extern u_long Storage_lastobj, Storage_lastobjend;
  58. extern bool Storage_proto;
  59.  
  60. //---- Object ------------------------------------------------------------------
  61.  
  62. int Object::_an;
  63. AccessMembers *Object::_accessMembers;
  64.  
  65. //---- automatically added by macro metaImpl -----------------------------------
  66.  
  67. Class *Object::isa;
  68.  
  69. static Class ObjectClassMetaImpl0("Object",
  70.                   sizeof (Object),
  71.                   new Object((_dummy*)0),
  72.                   __FILE__,
  73.                   "./Object.h",
  74.                   __LINE__,
  75.                   1,
  76.                   TRUE);
  77.  
  78. Object::Object(class _dummy*)
  79. {
  80.     Storage_proto= TRUE;
  81.     flags= cObjNonDeleted | cObjIsProto;
  82.     if ((u_long)this >= Storage_lastobj && (u_long)this < Storage_lastobjend)
  83.     SetFlag(cObjIsShared);
  84.     isa= &ObjectClassMetaImpl0;
  85.     ObjectClassMetaImpl0.SetSuper();
  86. }
  87.  
  88. Class *Object::IsA()
  89. {
  90.     return &ObjectClassMetaImpl0;
  91. }
  92.  
  93. void Object::Members(AccessMembers *ac)
  94. {
  95.     _accessMembers= ac;
  96.     ScanMembers(TX(flags), TP(Observer), TP(DelayedChanges), TP(isa));
  97. }
  98.  
  99. //---- ordinary methods ----------------------------------------------------
  100.  
  101. Object::Object(int f)
  102. {
  103.     flags= (f & cFlagMask) | cObjNonDeleted;
  104.     if ((u_long)this >= Storage_lastobj && (u_long)this < Storage_lastobjend) {
  105.     SetFlag(cObjIsShared);
  106.     if (Storage_proto)
  107.         flags|= cObjIsProto;
  108.     }
  109.     ObjectTable::Add(this);
  110. }
  111.  
  112. Object::~Object()
  113. {
  114.     if (! TestFlag(cObjNonDeleted))
  115.     Fatal("~Object", "object deleted twice");
  116.       
  117.     if (IsObserved()) {
  118.     Collection *observers= GetObservers(); // GetObservers is statically bound!!!
  119.     flags &= ~cObjIsObserved;
  120.     if (observers)
  121.         CleanupObservers(observers);
  122.     }
  123.     flags&= ~cObjNonDeleted;
  124.     ObjectTable::Remove(this);
  125. }
  126.  
  127. void Object::FreeAll()
  128. {
  129. }
  130.  
  131. //----- flag manipulation ------------------------------------------------------
  132.  
  133. void Object::SetFlag(int f, bool b)
  134. {
  135.     if (b)
  136.     SetFlag(f);
  137.     else
  138.     ResetFlag(f);
  139. }
  140.  
  141. //---- attributes --------------------------------------------------------------
  142.  
  143. char *Object::ClassName()
  144. {
  145.     return IsA()->Name();
  146.  
  147. //---- comparing ---------------------------------------------------------------
  148.  
  149. u_long Object::Hash () 
  150. {
  151.     return (u_long) this;
  152. }
  153.  
  154. bool Object::IsEqual(Object *anOp)
  155. {
  156.      return anOp == this;
  157. }
  158.  
  159. int Object::Compare(Object*)
  160. {
  161.     AbstractMethod ("Compare");
  162.     return 0;
  163. }
  164.  
  165. //---- converting, activation/passivation ------------------------------------
  166.  
  167. char* Object::AsString()
  168. {
  169.     return 0;
  170. }
  171.  
  172. static bool printOnWhenObserved(Object*, Object* op, Object *from)
  173. {
  174.     return op->PrintOnWhenObserving(from);
  175. }
  176.  
  177. OStream &Object::PrintOn(OStream &os)
  178. {
  179.     Collection *selectedDeps= 0;
  180.        
  181.     os.MakeIndex(this);
  182.     if (IsObserved()) {
  183.     Collection *observers= GetObservers();
  184.     if (observers->IsEmpty()) { // impossible ??
  185.         flags &= ~cObjIsObserved;
  186.         DestroyObserverColl();
  187.     } else {
  188.         selectedDeps= observers->Select((BoolFun)printOnWhenObserved, this);
  189.         if (selectedDeps->IsEmpty())
  190.         SafeDelete(selectedDeps);
  191.     }
  192.     }
  193.     os << (flags & cFlagMask) SP << selectedDeps SP;
  194.     SafeDelete(selectedDeps);
  195.     return os;
  196. }
  197.  
  198. OStream &operator<< (OStream &os, Object *op)
  199. {
  200.     int ix;
  201.  
  202.     if ((op == 0) || (op == op->IsA())) {       // a null pointer
  203.     os.put('0');                            // "0" seems to be portable!
  204.  
  205.     } else if ((ix= os.IndexOfPtr(op)) >= 0 ) { // already in table ?
  206.     os.put('@');
  207.     os << ix;                               // write index
  208.     
  209.     } else {
  210.     Object *op2;
  211.     // special case: we are copying inside a single address space
  212.     // try if class has overwritten deepclone
  213.     if (os.IsForDeepClone() && (op2= op->deepclone())) {
  214.         os.put('#');
  215.         os << os.MakeIndex(op) SP << (u_long) op2;
  216.     } else {
  217.         if (! op->IsKindOf(Class))
  218.         os.put('\n');                   // pretty printing
  219.         os.put('{');
  220.         os << os.MakeIndex(op) SP << op->IsA();
  221.         op->PrintOn(os);
  222.         os.put('}');
  223.     }
  224.     }
  225.     os.put(' ');
  226.     os.flush();
  227.     return os;
  228. }
  229.  
  230. IStream &Object::ReadFrom(IStream &is)
  231. {
  232.     int f;
  233.     Collection *observers;
  234.     
  235.     is.MakeIndex(this);
  236.     is >> f >> observers;
  237.     SetFlag(f);
  238.     if (observers) {
  239.     flags |= cObjIsObserved;
  240.     SetObserverColl(observers);
  241.     }
  242.     return is;
  243. }
  244.  
  245. Object *Object::ReadAndMap(IStream &is)
  246. {
  247.     Object *op= New();
  248.     (*op).ReadFrom(is);
  249.     return op;
  250. }
  251.  
  252. /* Read in new object, put a pointer to it in *op.
  253. *  Make sure object read in is cl or a descendant of cl.
  254. */
  255. IStream& LoadPtr(IStream &is, Object *&op, Class *expected)
  256. {
  257.     static char *cLoadError= "Object::LoadPtr";
  258.     Class *clp= 0;
  259.     char c= 0;
  260.     int ix= 0;
  261.     u_long ptr= 0;
  262.  
  263.     op= 0;
  264.  
  265.     is >> c;
  266.  
  267.     switch (c) {
  268.     
  269.     case '0':       // a nil pointer
  270.     return is;
  271.     
  272.     case '#':       // a real address from DeepCopy
  273.     is >> ix >> ptr;
  274.     if (is.IsForDeepClone()) {
  275.         op= (Object*) ptr;
  276.         is.AtPut(ix, op);
  277.     } else
  278.         Error(cLoadError, "shouldn't happen: got address %d", ptr);
  279.     break;
  280.  
  281.     case '@':       // table index of existing object
  282.     is >> ix;
  283.     op= is.At(ix);
  284.     if (op == (Object*) 0x01) {
  285.         Error(cLoadError, "object is 1", ix);
  286.         op= 0;
  287.     } else if (op == 0)
  288.         Error(cLoadError, "can't find element %d in instancetable", ix);
  289.     break;
  290.  
  291.     case '{':       // new object
  292.     is >> ix >> clp;
  293.     if (clp == 0)   // assume class "Class"
  294.         clp= Meta(Class);
  295.         
  296.     op= clp->Proto()->ReadAndMap(is);
  297.     is.AtPut(ix, op);
  298.  
  299.     int level= 1;
  300.     bool first= TRUE;
  301.     while (is.get(c)) {
  302.         if (c == '{') {
  303.         level++;
  304.         continue;
  305.         }
  306.         if (c == '}') {
  307.         level--;
  308.         if (level <= 0)
  309.             break;
  310.         continue;
  311.         }
  312.         if (!Isspace(c)) {
  313.         if (first) {
  314.             Error(cLoadError, "expected \'}\' at end of <%s>; got: (%02x)",
  315.                                 clp->Name(), c);
  316.             first= FALSE;
  317.         }
  318.         }
  319.     };
  320.     break;
  321.  
  322.     default:
  323.     Error(cLoadError, "unexpected character 0x%02x", c & 0xff);
  324.     break;
  325.     }
  326.     
  327.     if (op == 0) {
  328.     if (expected) {
  329.         Error(cLoadError, "can't read object; creating dummy instance of %s",
  330.                                 expected->Name());
  331.         op= expected->Proto()->New();
  332.     }
  333.     } else if (expected) {
  334.     Class *clp= op->IsA();
  335.     if (clp && !clp->isKindOf(expected))
  336.         Error(cLoadError, "trying to read a %s into a %s", clp->Name(),
  337.                                 expected->Name());
  338.     }
  339.  
  340.     return is;
  341. }
  342.  
  343. //---- cloning -----------------------------------------------------------------
  344.  
  345. Object *Object::New()
  346. {
  347.     Object *op= IsA()->Proto()->Object::Clone();
  348.     op->InitNew();
  349.     return op;
  350. }
  351.  
  352. void Object::InitNew()
  353. {
  354. }
  355.  
  356. Object *Object::Clone()
  357. {
  358.     Object *op= (Object*) Storage::ObjectAlloc(IsA()->Size());
  359.     // give the new object the correct vtable in a portable? way
  360.     memcpy(op, this, IsA()->Size());
  361.     op->flags |= cObjNonDeleted | cObjIsShared;
  362.     op->flags &= ~cObjIsProto;
  363.     ObjectTable::Add(op);
  364.     return op;
  365. }
  366.  
  367. Object *Object::deepclone()
  368. {
  369.     return 0;
  370. }
  371.  
  372. Object *Object::DeepClone()
  373. {
  374.     Object* op;
  375.     
  376.     if (op= deepclone())
  377.     return op;
  378.     
  379.     MemBuf mb;
  380.     OStream to(&mb);
  381.     IStream from(&mb);
  382.     
  383.     to.PrepareForDeepClone();
  384.     to << this;
  385.     to.flush();
  386.  
  387.     mb.SwitchToRead();
  388.     
  389.     from.PrepareForDeepClone();
  390.     from >> op;
  391.  
  392.     return op;
  393. }
  394.  
  395. //---- change propagation, object observing ------------------------------------
  396.  
  397. Collection *Object::MakeObserverColl()
  398. {
  399.     Collection *cp;
  400.     if (Observer == 0)
  401.     Observer= new IdDictionary(70);
  402.     if (cp= (Collection*) Observer->AtKey(this))
  403.     Warning("MakeObserverColl", "there are already Observers for %s", ClassName());
  404.     else {
  405.     cp= new OrdCollection;
  406.     Observer->PutAtKeyIfAbsent(cp, this);
  407.     }
  408.     return cp;
  409. }
  410.  
  411. Collection *Object::GetObservers()
  412. {
  413.     if (Observer == 0) {
  414.     Warning("GetObservers", "without SetObserver");
  415.     return 0;
  416.     }      
  417.     Collection *cp= (Collection*) Observer->AtKey(this);
  418.     if (cp == 0) 
  419.     Warning("GetObservers", "observers == 0 in GetObservers for %s", ClassName());
  420.     return cp;
  421. }
  422.  
  423. void Object::DestroyObserverColl()
  424. {
  425. #ifdef OLD
  426.     if (Observer) {
  427.     Assoc *ap= (Assoc*) Observer->RemoveKey(this);
  428.     if (ap) {
  429.         Object *observers= ap->Value();
  430.         if (observers) {
  431.         SafeDelete(observers);
  432.         } else
  433.         Warning ("DestroyObserverColl", "0 in DestroyObserverColl() for %s",
  434.                                 ClassName());
  435.         SafeDelete(ap);
  436.     }
  437.     } else
  438.     Warning("DestroyObserverColl", "Observer == 0");
  439. #endif
  440.  
  441.     if (Observer) {
  442.     Object *value;
  443.     if (Observer->RemoveKey(this, value)) { 
  444.         // could also check for IsObserved
  445.         if (value) {
  446.         SafeDelete(value);      // value is a container
  447.         } else
  448.         Warning("DestroyObserverColl", "0 in DestroyObserverColl() for %s",
  449.             ClassName());
  450.     }
  451.     } else
  452.     Warning("DestroyObserverColl", "Observer == 0");
  453. }
  454.  
  455. void Object::SetObserverColl(Collection *cp)
  456. {
  457.     DestroyObserverColl();
  458.     if (Observer == 0)
  459.     Observer= new IdDictionary(70);
  460.     Observer->PutAtKeyIfAbsent(cp, this);
  461. }
  462.  
  463. void Object::CleanupObservers(Collection *observers)
  464. {
  465.     observers->ForEach(Object,DoObserve)(cIdNone, cPartSenderDied, 0, this);
  466.     DestroyObserverColl();
  467. }
  468.  
  469. void Object::AddObserver(Object* op)
  470. {
  471.     Collection *observer;
  472.     
  473.     if (op) {
  474.     if (!IsObserved() || ((observer= GetObservers()) == 0)) {
  475.         flags |= cObjIsObserved; 
  476.         observer= MakeObserverColl();
  477.     } else {
  478.         if (observer->FindPtr(op)) {
  479.         Warning("AddObserver", "duplicate in observers");
  480.         return;
  481.         }
  482.     }
  483.     observer->Add(op);
  484.     }
  485. }
  486.  
  487. Object* Object::RemoveObserver(Object* op)
  488. {
  489.     if (this && IsObserved()) {
  490.     Collection *observers= GetObservers();
  491.     if (observers) {
  492.         if (op) 
  493.         op= observers->RemovePtr(op);
  494.         if (observers->IsEmpty()) {
  495.         flags &= ~cObjIsObserved;
  496.         DestroyObserverColl();
  497.         }
  498.         return op;
  499.     }
  500.     }
  501.     return 0;
  502. }
  503.  
  504. void Object::Send(int id, int part, void *vp)
  505. {
  506.     if (!IsObserved())
  507.     return;
  508.  
  509.     if (TestFlag(cObjDelayChanges)) {
  510.     if (DelayedChanges) {
  511.         Collection *col= (Collection*) DelayedChanges->AtKey(this);
  512.         if (col == 0) {
  513.         Warning("Send", "No collection for change messages, %s", ClassName());
  514.         col= new OrdCollection;
  515.         DelayedChanges->PutAtKeyIfAbsent(col, this);
  516.         }
  517.         col->Add(new ChangeMessage(vp, part, id));
  518.     } else
  519.         Error("Send", "DelayedChanges still 0");
  520.     } else {
  521.     Collection *observers= GetObservers();
  522.     if (observers)
  523.         observers->ForEach(Object,DoObserve)(id, part, vp, this);
  524.     }
  525. }
  526.  
  527. void Object::DoObserve(int, int, void*, Object*)
  528. {
  529. }
  530.  
  531. class Iterator *Object::GetObserverIter()        
  532. {
  533.     if (!IsObserved())
  534.     return 0;
  535.     Collection *observers= GetObservers(); 
  536.     if (observers)
  537.     return observers->MakeIterator();
  538.     return 0;
  539. }
  540.  
  541. void Object::DelayChanges()
  542. {
  543.     SeqCollection *col= 0;
  544.     
  545.     flags |= cObjDelayChanges;
  546.     if (DelayedChanges == 0)
  547.     DelayedChanges= new IdDictionary;
  548.     else
  549.     col= (SeqCollection*) DelayedChanges->AtKey(this);
  550.     if (col) {
  551.     ObjInt *ref= (ObjInt*) col->At(0);
  552.     ++(*ref);
  553.     } else {
  554.     col= new OrdCollection;
  555.     col->Add(new ObjInt(0));
  556.     DelayedChanges->PutAtKeyIfAbsent(col, this);
  557.     }
  558. }
  559.  
  560. void Object::FlushChanges()
  561. {
  562.     if (DelayedChanges) {
  563.     SeqCollection *col= (SeqCollection*) DelayedChanges->AtKey(this);
  564.     if (col) {
  565.         ObjInt *ref= (ObjInt*)col->At(0);
  566.         if (ref->GetValue() <= 0) {
  567.         flags &= ~cObjDelayChanges;
  568.         ChangeMessage *cm;
  569.         Iter next(col);
  570.         next(); // overread reference count
  571.         while (cm= (ChangeMessage*) next()) 
  572.             Send(cm->id, cm->part, cm->what);
  573.         DelayedChanges->RemoveKey(this);
  574.         col->FreeAll();
  575.         SafeDelete(col);
  576.         } else 
  577.         (*ref)--;
  578.     }
  579.     }
  580. }
  581.  
  582. bool Object::PrintOnWhenObserving(Object*)
  583. {
  584.     return TRUE;    
  585. }
  586.  
  587. //---- error handling ----------------------------------------------------------
  588.  
  589. void Object::DoError(int level, char *location, char *fmt, va_list va)
  590. {
  591.     ::ErrorHandler(level, form("%s::%s", ClassName(), location), fmt, va);
  592. }
  593.  
  594. void Object::Error(char *location, char *va_(fmt), ...)
  595. {
  596.     va_list ap;
  597.     va_start(ap, va_(fmt));
  598.     DoError(cError, location, va_(fmt), ap);
  599.     va_end(ap);
  600. }
  601.  
  602. void Object::SysError(char *location,  char *va_(fmt), ...)
  603. {
  604.     va_list ap;
  605.     va_start(ap, va_(fmt));
  606.     DoError(cSysError, location, va_(fmt), ap);
  607.     va_end(ap);
  608. }
  609.  
  610. void Object::Warning(char *location, char *va_(fmt), ...)
  611. {
  612.     va_list ap;
  613.     va_start(ap, va_(fmt));
  614.     DoError(cWarning, location, va_(fmt), ap);
  615.     va_end(ap);
  616. }
  617.  
  618. void Object::Fatal(char *location, char *va_(fmt), ...)
  619. {
  620.     va_list ap;
  621.     va_start(ap, va_(fmt));
  622.     DoError(cFatal, location, va_(fmt), ap);
  623.     va_end(ap);
  624. }
  625.  
  626. //---- fire walls --------------------------------------------------------------
  627.  
  628. void Object::AbstractMethod(char *method)
  629. {
  630.     Warning(method, "abstract method called"); 
  631. }
  632.  
  633. void Object::MayNotUse(char *method)
  634. {
  635.     Warning(method, "not allowed to use this method");
  636. }
  637.  
  638. Object *Object::guard(Class *should)
  639. {
  640.     if (this && IsA()->isKindOf(should))
  641.     return this;
  642.     if (this)
  643.     Error("Guard", "object is not a %s but a %s", should->Name(), ClassName());
  644.     return 0;
  645. }
  646.  
  647. //---- inspecting, debugging ---------------------------------------------------
  648.  
  649. void Object::Inspect(bool block)
  650. {
  651.     gProgEnv->InspectObject(this, block);
  652. }
  653.  
  654. void Object::EditSource(bool definition)
  655. {
  656.     gProgEnv->EditSourceOf(IsA(), definition);
  657. }
  658.  
  659. void Object::InspectorId(char *buf, int bufSize)
  660. {
  661.     char *name= AsString();
  662.     if (name)
  663.     strn0cpy(buf, name, bufSize);
  664. }
  665.  
  666. void Object::CollectParts(class Collection *)
  667. {
  668. }
  669.  
  670. void Object::ScanMembers(u_long va_(firstTag), ...)
  671. {
  672.     int n= _an;
  673.     _an= 0;
  674.     va_list ap;
  675.     va_start(ap, va_(firstTag));
  676.     if (_accessMembers)
  677.     _accessMembers->ScanMembers(this, (int)va_(firstTag), ap, n);
  678.     va_end(ap);
  679. }
  680.  
  681. //---- interface for accessing instance variables by name will be improved
  682. //     in a future release
  683.  
  684.     class FindMember: public AccessMembers {
  685.     public:
  686.     const char *lookfor;
  687.     int offset, len, type;
  688.     Object *op;
  689.     Class *classp;
  690.         
  691.     FindMember(Object *in, const char *name)
  692.         { offset= -1; op= in; lookfor= name; type= 0; len= -1;}
  693.     void Member(char *name, int offset, int lenOrOffset, int type,
  694.                             Class*, bool g, bool lg);
  695.     };
  696.     
  697.     void FindMember::Member(char *name, int o, int, int t, Class *c, bool ,
  698.                                     bool)
  699.     {
  700.     if (strcmp(name, lookfor) == 0) {
  701.         offset= o;
  702.         type= t;
  703.         classp= c;
  704.         // if (l == -1)
  705.         // len= GetLength(op, o, l, t, c, g, lg);
  706.     }
  707.     }
  708.     
  709. void *Object::GetAddrOf(const char *name, Class *&cl)
  710. {
  711.     FindMember m(this, name);
  712.     IsA()->EnumerateMembers(&m);
  713.     if (m.offset != -1) {
  714.     cl= m.classp;
  715.     return (void*) ((u_long) this + (u_long) m.offset);
  716.     }
  717.     return 0;
  718. }
  719.  
  720.